wait関数は、呼び出し元プロセスの子プロセスの状態変化を待ちます。子プロセスの状態変化がすでに発生していた場合は、wait関数はすぐに復帰します。それ以外の場合は、子プロセスの状態変化が起こるか、シグナルハンドラによりシステムコールが中断されるまで呼び出し元プロセスは停止します。
なお、ここでの状態変化には、次のような事があります。
- 子プロセスの終了。
- シグナルによる子プロセスの停止。
- シグナルによる子プロセスの再開。
この関数は、C言語のライブラリ関数(標準関数)ではありませんので、コンパイラにより、使えない場合があります。
#include <sys/wait.h>
pid_t wait(int *status);
*statusは子プロセスからの終了ステータスを格納する変数を指定します。なお、終了ステータスが不要な場合は、NULLを指定できます。
戻り値として、処理が成功した場合は、子プロセスのプロセスIDが、失敗した場合は-1を返します。
終了ステータスはexit関数の引数で指定した値そのままではなく、「指定した値 & 0377」です。また、終了ステータスをチェックするための、次のようなマクロがあります。
| マクロ | 内容 |
|---|---|
| WIFEXITED(status) | 子プロセスが正常に終了した場合に真を返します。「正常」とは、exit関数の呼び出しや、main関数から復帰した場合です。 |
| WEXITSTATUS(status) | 子プロセスの終了ステータスを返します。終了ステータスはexit関数やmain関数の引数で指定した値です。なお、このマクロはWIFEXITEDマクロが真を返した場合だけ使用したほうがよいでしょう。 |
| WIFSIGNALED(status) | 子プロセスがシグナルにより終了した場合に真を返します。 |
| WTERMSIG(status) | 子プロセス終了の原因となったシグナルの番号を返します。このマクロはWIFSIGNALEDマクロが真を返した場合だけ使用したほうがよいでしょう。 |
プログラム 例
#include <stdio.h>
#include <sys/wait.h>
int main()
{
int p_id;
int status;
int return_code = 0;
if ((p_id = fork()) == 0) {
/* 子プロセス */
printf("子プロセス開始\n");
sleep(10);
printf("子プロセス終了\n");
}
else {
/* 親プロセス */
if (p_id != -1) {
/* 子プロセスの状態変化を待つ */
wait(&status);
/* 終了ステータスのチェック */
if (WIFEXITED(status)) {
printf("親プロセス : 子プロセスは終了ステータス%dで正常終了しました\n",
WEXITSTATUS(status));
}
if (WIFSIGNALED(status)) {
printf("親プロセス : 子プロセスはシグナル番号%dで終了しました\n",
WTERMSIG(status));
}
printf("親プロセス終了\n");
}
else {
perror("親プロセス ");
return_code = 1;
}
}
return return_code;
}
例の実行結果
2回目と3回目はバックグラウンドで実行して、psコマンドで子プロセスのプロセスIDを調べた後、killコマンドでシグナルを送っています。(その結果、子プロセスは終了します。)
$ ./wait.exe 子プロセス開始 子プロセス終了 親プロセス : 子プロセスは終了ステータス0で正常終了しました 親プロセス終了 $ $ ./wait.exe & 子プロセス開始 [1] 2731 $ ps PID TTY TIME CMD 2293 pts/1 00:00:00 bash 2731 pts/1 00:00:00 wait.exe 2732 pts/1 00:00:00 wait.exe 2733 pts/1 00:00:00 ps $ kill 2732 親プロセス : 子プロセスはシグナル番号15で終了しました 親プロセス終了 $ $ ./wait.exe & 子プロセス開始 [1] 2741 $ ps PID TTY TIME CMD 2293 pts/1 00:00:00 bash 2741 pts/1 00:00:00 wait.exe 2742 pts/1 00:00:00 wait.exe 2743 pts/1 00:00:00 ps $ kill -s SIGQUIT 2742 親プロセス : 子プロセスはシグナル番号3で終了しました 親プロセス終了 $